package org.ru.mse10.cvis.service;

import java.util.List;

import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.Query;

import org.ru.mse10.cvis.constants.UserNamedQueries;
import org.ru.mse10.cvis.entity.cv.User;
import org.ru.mse10.cvis.util.CommonUtil;
import org.ru.mse10.cvis.util.security.BCrypt;

/**
 * The Class UserService.
 */
@Stateless
public class UserService extends EntityService {

	/** The Constant QUERY_EMAIL_EXISTS_KEY. */
	public static final String QUERY_EMAIL_EXISTS_KEY = "QUERY_EMAIL_EXISTS_KEY";

	/** The Constant QUERY_EMAIL_EXISTS. */
	public static final String QUERY_EMAIL_EXISTS = "select u.id from User u where u.mail = :email";

	/** The Constant QUERY_USER_LOGIN_KEY. */
	public static final String QUERY_USER_LOGIN_KEY = "QUERY_USER_LOGIN_KEY";

	/** The Constant QUERY_USER_LOGIN. */
	public static final String QUERY_USER_LOGIN = "from User u where u.mail = :mail and u.password = :pass and u.confirmed = 1";

	/** The Constant QUERY_USER_BY_EMAIL_KEY. */
	public static final String QUERY_USER_BY_EMAIL_KEY = "QUERY_USER_BY_EMAIL_KEY";

	/** The Constant QUERY_USER_BY_EMAIL. */
	public static final String QUERY_USER_BY_EMAIL = "from User u where u.mail = :mail";

	/** The Constant QUERY_USER_ALL_KEY. */
	public static final String QUERY_USER_ALL_KEY = "QUERY_USER_ALL_KEY";

	/** The Constant QUERY_USER_ALL. */
	public static final String QUERY_USER_ALL = "from User";

	/**
	 * Checks if is existing user email.
	 * 
	 * @param email
	 *            the email
	 * @return true, if is existing user email
	 */
	public boolean isExistingUserEmail(String email) {
		if (CommonUtil.isEmpty(email)) {
			return false;
		}
		Query query = getEntityManager().createNamedQuery(
				UserNamedQueries.QUERY_CHECK_EMAIL_KEY).setParameter("email",
				email);
		@SuppressWarnings("rawtypes")
		List list = query.getResultList();
		return !CommonUtil.isEmpty(list);
	}

	/**
	 * Check login.
	 * 
	 * @param email
	 *            the email
	 * @param password
	 *            the password
	 * @return the long
	 */
	public Long checkLogin(String email, String password) {
		if (CommonUtil.isEmpty(email) || CommonUtil.isEmpty(password)) {
			return null;
		}
		Query queryHash = getEntityManager().createNamedQuery(
				UserNamedQueries.QUERY_HASH_BY_EMAIL_KEY).setParameter("email",
				email);

		@SuppressWarnings("unchecked")
		List<String> hashResults = queryHash.getResultList();
		if (CommonUtil.isEmpty(hashResults) || hashResults.size() != 1) {
			return null;
		}
		String pwdHash = hashResults.get(0);
		if (BCrypt.checkpw(password, pwdHash)) {
			Query query = getEntityManager()
					.createNamedQuery(UserNamedQueries.QUERY_CHECK_LOGIN_KEY)
					.setParameter("email", email).setParameter("pass", pwdHash);

			@SuppressWarnings("unchecked")
			List<Long> list = query.getResultList();
			if (list.size() == 1) {
				return list.get(0);
			}
		}
		return null;
	}

	/**
	 * Check login.
	 * 
	 * @param user
	 *            the user
	 * @return the user
	 */
	@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
	public User checkLogin(User user) {
		Query queryLoginUser = getEntityManager().createNamedQuery(
				QUERY_USER_LOGIN_KEY);
		queryLoginUser.setParameter("mail", user.getEmail());
		queryLoginUser.setParameter("pass",
				CommonUtil.hashPassword(user.getPassword()));

		@SuppressWarnings("unchecked")
		List<User> resultList = queryLoginUser.getResultList();
		if (CommonUtil.isEmpty(resultList)) {
			return resultList.get(0);
		}
		return null;
	}

	/**
	 * Method to take user from DB by email.
	 * 
	 * @param email
	 *            - email of user who have forgotten his password
	 * @return - the stupid user
	 */
	@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
	public User findUserByEmail(String email) {
		Query queryfindUserByEmail = getEntityManager().createNamedQuery(
				UserNamedQueries.QUERY_USER_BY_EMAIL_KEY);
		queryfindUserByEmail.setParameter("email", email);

		@SuppressWarnings("unchecked")
		List<User> resultList = queryfindUserByEmail.getResultList();
		if (CommonUtil.isEmpty(resultList)) {
			return null;
		}
		return resultList.get(0);
	}

}
